<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.2">
<title>Natural Ids</title>
<link rel="stylesheet" href="./css/hibernate.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js"></script>
<script>document.addEventListener('DOMContentLoaded', prettyPrint)</script>
</head>
<body class="article">
<div id="header">
</div>
<div id="content">
<div class="sect2">
<h3 id="naturalid">Natural Ids</h3>
<div class="paragraph">
<p>Natural ids represent domain model unique identifiers that have a meaning in the real world too.
Even if a natural id does not make a good primary key (surrogate keys being usually preferred), it&#8217;s still useful to tell Hibernate about it.
As we will see later, Hibernate provides a dedicated, efficient API for loading an entity by its natural id much like it offers for loading by its identifier (PK).</p>
</div>
<div class="sect3">
<h4 id="naturalid-mapping">Natural Id Mapping</h4>
<div class="paragraph">
<p>Natural ids are defined in terms of one or more persistent attributes.</p>
</div>
<div class="exampleblock">
<div class="title">Example 1. Natural id using single basic attribute</div>
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@Entity
public class Company {

    @Id
    private Integer id;

    @NaturalId
    private String taxIdentifier;

    ...
}</code></pre>
</div>
</div>
</div>
</div>
<div class="exampleblock">
<div class="title">Example 2. Natural id using single embedded attribute</div>
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@Entity
public class PostalCarrier {

    @Id
    private Integer id;

    @NaturalId
    @Embedded
    private PostalCode postalCode;

    ...

}

@Embeddable
public class PostalCode {
    ...
}</code></pre>
</div>
</div>
</div>
</div>
<div class="exampleblock">
<div class="title">Example 3. Natural id using multiple persistent attributes</div>
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@Entity
public class Course {

    @Id
    private Integer id;

    @NaturalId
    @ManyToOne
    private Department department;

    @NaturalId
    private String code;

    ...
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="naturalid-api">Natural Id API</h4>
<div class="paragraph">
<p>As stated before, Hibernate provides an API for loading entities by their associate natural id.
This is represented by the <code>org.hibernate.NaturalIdLoadAccess</code> contract obtained via Session#byNaturalId.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>If the entity does not define a natural id, trying to load an entity by its natural id will throw an exception.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="exampleblock">
<div class="title">Example 4. Using NaturalIdLoadAccess</div>
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">Session session = ...;

Company company = session.byNaturalId( Company.class )
    .using( "taxIdentifier","abc-123-xyz" )
    .load();

PostalCarrier carrier = session.byNaturalId( PostalCarrier.class )
    .using( "postalCode",new PostalCode(... ) )
    .load();

Department department = ...;
Course course = session.byNaturalId( Course.class )
    .using( "department",department )
    .using( "code","101" )
    .load();</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>NaturalIdLoadAccess offers 2 distinct methods for obtaining the entity:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>load()</code></dt>
<dd>
<p>obtains a reference to the entity, making sure that the entity state is initialized</p>
</dd>
<dt class="hdlist1"><code>getReference()</code></dt>
<dd>
<p>obtains a reference to the entity. The state may or may not be initialized.
If the entity is already associated with the current running Session, that reference (loaded or not) is returned.
If the entity is not loaded in the current Session and the entity supports proxy generation, an uninitialized proxy is generated and returned, otherwise the entity is loaded from the database and returned.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p><code>NaturalIdLoadAccess</code> allows loading an entity by natural id and at the same time apply a pessimistic lock.
For additional details on locking, see the <a href="chapters/locking/Locking.html#locking">Locking</a> chapter.</p>
</div>
<div class="paragraph">
<p>We will discuss the last method available on NaturalIdLoadAccess ( <code>setSynchronizationEnabled()</code> ) in <a href="#naturalid-mutability-caching">Natural Id - Mutability and Caching</a>.</p>
</div>
<div class="paragraph">
<p>Because the <code>Company</code> and <code>PostalCarrier</code> entities define "simple" natural ids, we can load them as follows:</p>
</div>
<div class="exampleblock">
<div class="title">Example 5. Using SimpleNaturalIdLoadAccess</div>
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">Session session = ...;

Company company = session.bySimpleNaturalId( Company.class )
    .load( "abc-123-xyz" );

PostalCarrier carrier = session.bySimpleNaturalId( PostalCarrier.class )
    .load( new PostalCode(... ) );</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Here we see the use of the <code>org.hibernate.SimpleNaturalIdLoadAccess</code> contract, obtained via <code>Session#bySimpleNaturalId().
`SimpleNaturalIdLoadAccess</code> is similar to <code>NaturalIdLoadAccess</code> except that it does not define the using method.
Instead, because these "simple" natural ids are defined based on just one attribute we can directly pass the corresponding value of that natural id attribute directly to the <code>load()</code> and <code>getReference()</code> methods.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>If the entity does not define a natural id, or if the natural id is not of a "simple" type, an exception will be thrown there.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="naturalid-mutability-caching">Natural Id - Mutability and Caching</h4>
<div class="paragraph">
<p>A natural id may be mutable or immutable. By default the <code>@NaturalId</code> annotation marks an immutable natural id attribute.
An immutable natural id is expected to never change its value.
If the value(s) of the natural id attribute(s) change, <code>@NaturalId(mutable=true)</code> should be used instead.</p>
</div>
<div class="exampleblock">
<div class="title">Example 6. Mutable natural id</div>
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@Entity
public class Person {

    @Id
    private Integer id;

    @NaturalId( mutable = true )
    private String ssn;

    ...
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Within the Session, Hibernate maintains a mapping from natural id values to entity identifiers (PK) values.
If natural ids values changed, it is possible for this mapping to become out of date until a flush occurs.
To work around this condition, Hibernate will attempt to discover any such pending changes and adjust them when the <code>load()</code> or <code>getReference()</code> methods are executed.
To be clear: this is only pertinent for mutable natural ids.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p>This <em>discovery and adjustment</em> have a performance impact.
If an application is certain that none of its mutable natural ids already associated with the Session have changed, it can disable that checking by calling <code>setSynchronizationEnabled(false)</code> (the default is true).
This will force Hibernate to circumvent the checking of mutable natural ids.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="exampleblock">
<div class="title">Example 7. Mutable natural id synchronization use-case</div>
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">Session session=...;

Person person = session.bySimpleNaturalId( Person.class ).load( "123-45-6789" );
person.setSsn( "987-65-4321" );

...

// returns null!
person = session.bySimpleNaturalId( Person.class )
    .setSynchronizationEnabled( false )
    .load( "987-65-4321" );

// returns correctly!
person = session.bySimpleNaturalId( Person.class )
    .setSynchronizationEnabled( true )
    .load( "987-65-4321" );</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Not only can this NaturalId-to-PK resolution be cached in the Session, but we can also have it cached in the second-level cache if second level caching is enabled.</p>
</div>
<div id="naturalid-caching" class="exampleblock">
<div class="title">Example 8. Natural id caching</div>
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@Entity
@NaturalIdCache
public class Company {

    @Id
    private Integer id;

    @NaturalId
    private String taxIdentifier;

    ...
}</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2017-02-16 12:14:38 +01:00
</div>
</div>
</body>
</html>